/*
 * @file     g_i2c.c
 * @brief    This file provides all the I2C firmware functions.
 *
 * Change Logs:
 * Date           Author             Version        Notes
 * 2021-05-14     dengzhiqian        V1.0.0         the first version
 */

/* Includes -----------------------------------------------------------------*/
#include "g_i2c.h"

/* Exported functions -------------------------------------------------------*/
/**
 * @method G_I2C_DeInit
 * @brief  Deinitializes the I2Cx peripheral registers to their default reset values.
 * @param  I2Cx: Select the I2C peripheral.
 *         This parameter can be one of the following values:
 *         MI2C0, MI2C1
 * @retval None
 */
void G_I2C_DeInit(I2C_TypeDef *I2Cx)
{
    _ASSERT(IS_I2C(I2Cx));

    I2Cx->CTRL1.reg = 0;
    I2Cx->CTRL2.reg = 0;
}

/**
 * @method G_I2C_Init
 * @brief  Initializes the I2Cx peripheral according to the specified
 *         parameters in the G_I2C_InitTypeDef.
 * @param  I2Cx: Select the I2C peripheral.
 *         This parameter can be one of the following values:
 *         MI2C0, MI2C1
 * @param  I2C_InitStruct: pointer to a G_I2C_InitTypeDef structure
 *         that contains the configuration information for the specified I2C0
 *         peripheral.
 * @retval None
 */
void G_I2C_Init(I2C_TypeDef *I2Cx, G_I2C_InitTypeDef *I2C_InitStruct)
{
    DMA_TypeDef *DMAx;

    _ASSERT(IS_I2C(I2Cx));

    I2Cx->CTRL1.bit.SCLL = I2C_InitStruct->scll;
    I2Cx->CTRL1.bit.SCLH = I2C_InitStruct->sclh;
    I2Cx->CTRL1.bit.STSU = I2C_InitStruct->stsu;
    I2Cx->CTRL1.bit.STHD = I2C_InitStruct->sthd;

    I2Cx->CTRL2.bit.SOSU = I2C_InitStruct->sosu;
    I2Cx->CTRL2.bit.DTSU = I2C_InitStruct->dtsu;
    I2Cx->CTRL2.bit.DTHD = I2C_InitStruct->dthd;

    DMAx = (DMA_TypeDef *)((int)I2Cx - sizeof(DMA_TypeDef));
    DMAx->CTRL.bit.RESET = SET;
    DMAx->CTRL.bit.RESET = RESET;
}

void G_I2C_ClearITPendingBit(I2C_TypeDef *I2Cx)
{
    DMA_TypeDef *DMAx = (DMA_TypeDef *)((uint32_t)I2Cx - sizeof(DMA_TypeDef));
    /* Write `1` to clear DMA interrupt */
    DMAx->CTRL.bit.CLEAR_INT = 1;
}

/**
 * @method G_I2C_ITConfig
 * @brief  Config the interrupt state of `I2Cx`
 * @param  I2Cx: Select the I2C peripheral.
 *         This parameter can be one of the following values:
 *         MI2C0, MI2C1
 * @param  NewState: The new state of `I2Cx` interrupt state
 * @retval None
 */
void G_I2C_ITConfig(I2C_TypeDef *I2Cx, G_FunctionalState NewState)
{
    DMA_TypeDef *DMAx = (DMA_TypeDef *)((uint32_t)I2Cx - sizeof(DMA_TypeDef));
    DMAx->CTRL.bit.INT_MODE = NewState;
}

G_ITStatus G_I2C_GetITStatus(I2C_TypeDef *I2Cx)
{
    DMA_TypeDef *DMAx = (DMA_TypeDef *)((uint32_t)I2Cx - sizeof(DMA_TypeDef));
    return (G_ITStatus)(DMAx->CTRL.bit.INT_MODE);
}

/**
 * @method G_I2C_SendData
 * @brief  Write one byte to slave devices.
 * @param  I2Cx: Select the I2C peripheral.
 *         This parameter can be one of the following values:
 *         MI2C0, MI2C1
 * @param  Src: pointer to the buffer that contains the data you want to send.
 * @param  len: the length of send data
 * @note     After writting slave device, must delay a period of time before reading slave device.
 * @retval None
 */
void G_I2C_SendData(I2C_TypeDef *I2Cx, uint8_t data)
{
    uint8_t send_buf[1];
    DMA_TypeDef *DMAx;

    _ASSERT(IS_I2C(I2Cx));

    send_buf[0] = data;
    I2Cx->CTRL2.bit.RESTART = I2C_WRITE_FUNC;

    DMAx = (DMA_TypeDef *)((uint32_t)I2Cx - sizeof(DMA_TypeDef));
    DMAx->SRC_ADDR.reg               = (uint32_t)send_buf;
    DMAx->LEN_LOW.bit.TX_LEN_L = 1;
    DMAx->LEN_LOW.bit.RX_LEN_L = 0;
    DMAx->CTRL.bit.TX_LEN_H    = 0;
    DMAx->CTRL.bit.START          = 1;

    while (DMAx->STATUS.bit.DONE != 1);
}

/**
 * @method G_I2C_SendBytes
 * @brief  Write data to slave devices.
 * @param  I2Cx: Select the I2C peripheral.
 *         This parameter can be one of the following values:
 *         MI2C0, MI2C1
 * @param  Src: pointer to the buffer that contains the data you want to send.
 * @param  len: the length of send data
 * @note     After writting slave device, must delay a period of time before reading slave device.
 * @retval None
 */
void G_I2C_SendBytes(I2C_TypeDef *I2Cx, uint8_t *Src, uint32_t len)
{
    DMA_TypeDef *DMAx;

    _ASSERT(IS_I2C(I2Cx));
    _ASSERT(len < 0xfffff);
    I2Cx->CTRL2.bit.RESTART = I2C_WRITE_FUNC;

    DMAx = (DMA_TypeDef *)((uint32_t)I2Cx - sizeof(DMA_TypeDef));
    DMAx->SRC_ADDR.reg               = (uint32_t)Src;
    DMAx->LEN_LOW.bit.TX_LEN_L = len & 0xffff;
    DMAx->CTRL.bit.TX_LEN_H    = len >> 16;
    DMAx->LEN_LOW.bit.RX_LEN_L = 0;
    DMAx->CTRL.bit.RX_LEN_H    = 0;
    DMAx->CTRL.bit.START       = 1;

    while (DMAx->STATUS.bit.DONE != 1);
}

/**
 * @method G_I2C_ReceiveBytes
 * @brief  Read data from slave devices.
 * @param  I2Cx: Select the I2C peripheral.
 *         This parameter can be one of the following values:
 *         MI2C0, MI2C1
 * @param  Src: pointer to the buffer that contains the data you want to send.
 * @param  len: the length of send data
 * @param  Dest: pointer to the buffer that contains the data received from slaver.
 * @param  Destlen: the length of received data
 * @retval None
 */
void G_I2C_ReceiveBytes(I2C_TypeDef *I2Cx, uint8_t *Src, uint32_t Srclen, uint8_t *Dest, uint32_t Destlen)
{
    DMA_TypeDef *DMAx;

    _ASSERT(IS_I2C(I2Cx));
    _ASSERT(Srclen < 0xfffff);
    _ASSERT(Destlen < 0xfffff);
	/*GKT modify*/
    //I2Cx->CTRL2.bit.RESTART = I2C_READ_FUNC;

    DMAx = (DMA_TypeDef *)((uint32_t)I2Cx - sizeof(DMA_TypeDef));
    DMAx->SRC_ADDR.reg              = (uint32_t)Src;
    DMAx->DEST_ADDR.reg             = (uint32_t)Dest;
    DMAx->LEN_LOW.bit.TX_LEN_L      = Srclen & 0xffff;
    DMAx->CTRL.bit.TX_LEN_H         = Srclen >> 16;
    DMAx->LEN_LOW.bit.RX_LEN_L      = Destlen & 0xffff;
    DMAx->CTRL.bit.RX_LEN_H         = Destlen >> 16;
    DMAx->CTRL.bit.START            = 1;

    while (DMAx->STATUS.bit.DONE != 1);
}

/************************ (C) COPYRIGHT GKT *****END OF FILE****/
